package com.zxk;

import cn.hutool.core.collection.CollectionUtil;
import com.sun.jna.platform.win32.*;
import com.zxk.constant.JNAConstants;
import com.zxk.constant.ParamConstants;
import com.zxk.util.HwndUtil;
import com.zxk.util.KeyUtil;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 主程序入口
 *
 * @author: 舟小亢
 * @date: 2023-07-18 22:20
 */
public class StartController {

    private static Logger LOG = LoggerFactory.getLogger(com.zxk.controller.StartController.class);

    /**
     * 测试获取雷电模拟器句柄，并移动窗口
     */
    @Test
    public void test_moveWindow_when_hwnd_exist() {
        // 获取句柄
        // 第一个参数是Windows窗体的窗体类，第二个参数是窗体的标题
        WinDef.HWND hwnd = User32.INSTANCE.FindWindow(null, "梦幻西游：时空");

        // 设置活动窗口
        User32.INSTANCE.SetForegroundWindow(hwnd);

        System.out.println(hwnd);

        if (hwnd == null) {
            System.out.println("QQ is not running");
        } else {
            // SW_RESTORE
            User32.INSTANCE.ShowWindow(hwnd, 9);

            // bring to front
            User32.INSTANCE.SetForegroundWindow(hwnd);

            //User32.INSTANCE.GetForegroundWindow() //获取现在前台窗口
            WinDef.RECT qqwin_rect = new WinDef.RECT();
            User32.INSTANCE.GetWindowRect(hwnd, qqwin_rect);
            int qqwin_width = qqwin_rect.right - qqwin_rect.left;
            int qqwin_height = qqwin_rect.bottom - qqwin_rect.top;

            User32.INSTANCE.MoveWindow(hwnd, 700, 100, qqwin_width, qqwin_height, true);
            for (int i = 700; i > 100; i -= 10) {
                User32.INSTANCE.MoveWindow(hwnd, i, 100, qqwin_width, qqwin_height, true);   // bring to front
                try {
                    Thread.sleep(80);
                } catch (Exception e) {
                }
            }
            //User32.INSTANCE.PostMessage(hwnd, WinUser.WM_CLOSE, null, null);  // can be WM_QUIT in some occasio
        }
    }

    @Test
    public void exam_INPUT() {
        // 定义INPUT结构体数组
        WinUser.INPUT[] inputs = new WinUser.INPUT[1];

        // 设置类型：鼠标事件
        inputs[0].type = new WinDef.DWORD(WinUser.INPUT.INPUT_MOUSE);
        // 设置信息
        inputs[0].input.setType("mi");
        inputs[0].input.mi.dx = new WinDef.LONG(420);
        inputs[0].input.mi.dy = new WinDef.LONG(272);
        inputs[0].input.mi.mouseData = new WinDef.DWORD(0);
        long MOUSEEVENTF_LEFTDOWN = 0x0002;
        long MOUSEEVENTF_LEFTUP = 0x0004;
        inputs[0].input.mi.dwFlags = new WinDef.DWORD(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP);
        inputs[0].input.mi.time = new WinDef.DWORD(0);
        inputs[0].input.mi.dwExtraInfo = new BaseTSD.ULONG_PTR(0);

        // 发送输入事件
        User32.INSTANCE.SendInput(new WinDef.DWORD(1), inputs, inputs[0].size());
    }

    @Test
    public void test_leftButton_click() {
        // 获取句柄
        // 第一个参数是Windows窗体的窗体类，第二个参数是窗体的标题
        WinDef.HWND hwnd0 = User32.INSTANCE.FindWindow(null, "雷电模拟器");
        WinDef.HWND hwnd = User32.INSTANCE.FindWindowEx(hwnd0, null, null, "TheRender");
        // WinDef.HWND hwnd = User32.INSTANCE.FindWindowEx(hwnd1, null, null, "sub");

        WinDef.RECT rect = new WinDef.RECT();
        User32.INSTANCE.GetWindowRect(hwnd0, rect);
        System.out.println("左:" + rect.left + "上:" + rect.top + "右:" + rect.right + "下:" + rect.bottom);

        User32.INSTANCE.GetWindowRect(hwnd, rect);
        System.out.println("左:" + rect.left + "上:" + rect.top + "右:" + rect.right + "下:" + rect.bottom);
        // 点击登录游戏
        int x = 440 - rect.left;
        int y = 195 - rect.top;
        // 鼠标左键
        long MK_LBUTTON = 0x0001;
        int WM_LBUTTONDOWN = 0x0201;
        int WM_LBUTTONUP = 0x0202;

        // 高位为y坐标，低位为x坐标
        long postion = (x & 0xffff) | (y & 0xffffL) << 16;

        long VK_F11 = 0x7A;

        User32.INSTANCE.PostMessage(hwnd, WM_LBUTTONDOWN, new WinDef.WPARAM(MK_LBUTTON), new WinDef.LPARAM(postion));
        User32.INSTANCE.PostMessage(hwnd, WM_LBUTTONUP, new WinDef.WPARAM(MK_LBUTTON), new WinDef.LPARAM(postion));
        User32.INSTANCE.PostMessage(hwnd, User32.WM_KEYDOWN, new WinDef.WPARAM(VK_F11), new WinDef.LPARAM());
        User32.INSTANCE.PostMessage(hwnd, User32.WM_KEYUP, new WinDef.WPARAM(VK_F11), new WinDef.LPARAM());

        WinDef.POINT point = new WinDef.POINT();
        User32.INSTANCE.GetCursorPos(point);
        System.out.println(point.x + "-" + point.y);
    }

    /**
     * 获取鼠标位置
     */
    @Test
    public void get_mouse_position() {
        WinDef.POINT point = new WinDef.POINT();
        User32.INSTANCE.GetCursorPos(point);
        System.out.println(point.x + "-" + point.y);
    }

    /**
     * 模拟移动鼠标和滑动滚轮
     */
    @Test
    public void test_movemouse_and_slide_mousewheel() {
        // 测试任务

        WinDef.HWND hwnd_0 = User32.INSTANCE.FindWindow(null, JNAConstants.HANDLE_0);
        WinDef.HWND hwnd_1 = User32.INSTANCE.FindWindowEx(hwnd_0, null, null, JNAConstants.HANDLE_1);

        System.out.println(hwnd_0);
        System.out.println(hwnd_1);

        // 高16位为y坐标，低16位为x坐标
        int x = 900;
        int y = 300;
        y = y + ParamConstants.Y_ACCURACY;
        x = x + ParamConstants.X_ACCURACY;
        long postion = (x & 0xffff) | (y & 0xffffL) << 16;
        // long postion1 = ((x) & 0xffff) | ((y + 200) & 0xffffL) << 16;
        // User32.INSTANCE.PostMessage(hwnd_1, OperConstants.WM_LBUTTONDOWN, new WinDef.WPARAM(0), new WinDef.LPARAM(postion));
        // User32.INSTANCE.PostMessage(hwnd_1, OperConstants.WM_MOUSEMOVE, new WinDef.WPARAM(0), new WinDef.LPARAM(postion1));
        // User32.INSTANCE.SendMessage(hwnd_1, OperConstants.WM_LBUTTONUP, new WinDef.WPARAM(0), new WinDef.LPARAM(postion1));
        // WinDef.POINT point = new WinDef.POINT();
        // User32.INSTANCE.GetCursorPos(point);
        // System.out.println(point.x + "-" + point.y);
        // 发送鼠标滚动命令

        // 滚动距离。高16位代表滚动距离，正数负数分别表示不同的滚动方向，低16位默认为0
        long d = 120 << 16;
        // User32.INSTANCE.SendMessage(hwnd_1, OperConstants.WM_MOUSEWHEEL, new WinDef.WPARAM(d), new WinDef.LPARAM(postion));
        User32.INSTANCE.SetForegroundWindow(hwnd_1);

        // 组合键暂时不行
        KeyUtil.kMultiClick(hwnd_1, User32.VK_LMENU, JNAConstants.VK_M);
    }

    @Test
    public void test_set_window_position() {
        WinDef.HWND hwnd_0 = User32.INSTANCE.FindWindow(null, "梦幻西游：时空");
        WinDef.HWND hwnd_1 = User32.INSTANCE.FindWindowEx(hwnd_0, null, null, JNAConstants.HANDLE_1);
        System.out.println(hwnd_0);
        System.out.println(hwnd_1);
        WinDef.RECT rect = new WinDef.RECT();
        User32.INSTANCE.GetWindowRect(hwnd_0, rect);
        User32.INSTANCE.SetWindowPos(hwnd_0, null, 0, 0, rect.right - rect.left, rect.bottom - rect.top, 0);

    }

    @Test
    public void test_find_hwnds() {
        List<WinDef.HWND> hwnds = HwndUtil.getHwnds("时空");
        if (CollectionUtil.isEmpty(hwnds)) {
            return;
        }
        for (WinDef.HWND hwnd : hwnds) {
            WinDef.HWND hwnd_0 = hwnd;
            WinDef.HWND hwnd_1 = User32.INSTANCE.FindWindowEx(hwnd_0, null, null, JNAConstants.HANDLE_1);
            WinDef.HWND hwnd_2 = User32.INSTANCE.FindWindowEx(hwnd_1, null, null, JNAConstants.HANDLE_2);
            LOG.info("开启第[{}]个线程");
        }
    }

    @Test
    public void test_find_hwnds_and_operation() {
        List<WinDef.HWND> hwnds = HwndUtil.getHwnds("梦幻西游手游");
        if (CollectionUtil.isEmpty(hwnds)) {
            return;
        }
        for (WinDef.HWND hwnd : hwnds) {
            WinDef.HWND hwnd_0 = hwnd;
            WinDef.HWND hwnd_1 = User32.INSTANCE.FindWindowEx(hwnd_0, null, "ToolbarWindow32", null);
            System.out.println(hwnd_1.getPointer());
            // 调整位置
            WinDef.RECT rect = new WinDef.RECT();
            User32.INSTANCE.GetWindowRect(hwnd_1, rect);
            LOG.info("屏幕长{},宽{}", rect.right - rect.left, rect.bottom - rect.top);
            User32.INSTANCE.SetWindowPos(hwnd_1, null, 0, 0, 968, 589, 0);
            LOG.info("重置长968,宽589");
            // MouseUtil.lClickRandom(hwnd_0, 150, 150);
            // WinDef.HWND hwnd_2 = User32.INSTANCE.FindWindowEx(hwnd_1, null, null, JNAConstants.HANDLE_2);
            LOG.info("开启第[{}]个线程");
        }
    }

}
